"""
HTML模板文件
包含AI Chat Server的前端界面HTML代码
"""

HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI Chat</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background-color: #343541;
            color: #FFFFFF;
            min-height: 100vh;
        }

        .chat-container {
            max-width: 1200px;
            margin: 0 auto;
            height: 100vh;
            display: flex;
            flex-direction: column;
        }

        .chat-header {
            padding: 1rem;
            text-align: center;
            border-bottom: 1px solid #4a4b53;
            background-color: #444654;
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .chat-header h1 {
            font-size: 1.5rem;
            margin-bottom: 1rem;
            background: linear-gradient(90deg, #19c37d, #8e44ad);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .model-cards-container {
            display: flex;
            gap: 1rem;
            overflow-x: auto;
            padding: 1rem;
            scroll-behavior: smooth;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: thin;
            scrollbar-color: #565869 #343541;
        }

        .model-cards-container::-webkit-scrollbar {
            height: 6px;
        }

        .model-cards-container::-webkit-scrollbar-track {
            background: #343541;
        }

        .model-cards-container::-webkit-scrollbar-thumb {
            background-color: #565869;
            border-radius: 3px;
        }

        .model-card {
            flex: 0 0 auto;
            width: 200px;
            height: 120px;
            border-radius: 1rem;
            background: linear-gradient(135deg, #444654, #343541);
            border: 2px solid transparent;
            transition: all 0.3s ease;
            cursor: pointer;
            position: relative;
            overflow: hidden;
            padding: 1rem;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
        }

        .model-card.selected {
            border-color: #19c37d;
            transform: translateY(-2px);
            box-shadow: 0 8px 16px rgba(0,0,0,0.2);
        }

        .model-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 12px 24px rgba(0,0,0,0.3);
        }

        .model-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(25, 195, 125, 0.1), rgba(142, 68, 173, 0.1));
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .model-card:hover::before {
            opacity: 1;
        }

        .model-card span {
            font-size: 1.1rem;
            font-weight: 500;
            margin-bottom: 0.5rem;
        }

        .model-card small {
            font-size: 0.9rem;
            opacity: 0.8;
        }

        .chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: 1rem;
            display: flex;
            flex-direction: column;
            gap: 1rem;
        }

        .message {
            padding: 1rem;
            border-radius: 1rem;
            max-width: 100%;
            position: relative;
            animation: message-fade-in 0.3s ease-out;
            background: rgba(68, 70, 84, 0.7);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(86, 88, 105, 0.3);
        }
                @keyframes message-fade-in {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .user-message {
            background: rgba(52, 53, 65, 0.7);
            margin-left: auto;
            color: #FFFFFF;
            align-self: flex-end;
            max-width: 85%;
        }

        .assistant-message {
            margin-right: auto;
            color: #FFFFFF;
            width: 100%;
        }

        .system-message {
            background: rgba(142, 68, 173, 0.2);
            padding: 0.5rem 1rem;
            border-radius: 0.5rem;
            text-align: center;
            font-size: 0.9rem;
            color: #FFFFFF;
            margin: 0.5rem 0;
            animation: message-fade-in 0.3s ease-out;
        }

        .responses-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 1.5rem;
            padding: 1rem;
            transition: all 0.3s ease;
        }

        .response-card {
            background: rgba(68, 70, 84, 0.7);
            backdrop-filter: blur(10px);
            border-radius: 1rem;
            padding: 1.5rem;
            animation: slideIn 0.5s ease-out;
            position: relative;
            border: 1px solid rgba(86, 88, 105, 0.3);
        }

        .response-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 3px;
            background: linear-gradient(90deg, #19c37d, #8e44ad);
            border-radius: 3px 3px 0 0;
            transform: scaleX(0);
            transform-origin: left;
            transition: transform 0.3s ease;
        }

        .response-card.loading::before {
            transform: scaleX(1);
            animation: loading 2s infinite linear;
            background-size: 200% 100%;
        }

        @keyframes loading {
            0% { background-position: 200% 0; }
            100% { background-position: -200% 0; }
        }

        .message-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 0.8rem;
            padding-bottom: 0.5rem;
            border-bottom: 1px solid rgba(86, 88, 105, 0.3);
            font-size: 0.9rem;
            color: #acacbe;
        }

        .response-metrics {
            display: flex;
            gap: 1rem;
            font-size: 0.8rem;
            color: #acacbe;
            margin-top: 0.5rem;
            padding-top: 0.5rem;
            border-top: 1px solid rgba(86, 88, 105, 0.3);
        }

        .chat-input-container {
            padding: 1rem;
            background-color: #444654;
            border-top: 1px solid #4a4b53;
            display: flex;
            gap: 1rem;
            position: sticky;
            bottom: 0;
        }

        .typing-indicator {
            display: flex;
            gap: 0.3rem;
            padding: 0.5rem 0;
            align-items: center;
        }

        .typing-dot {
            width: 6px;
            height: 6px;
            background: linear-gradient(90deg, #19c37d, #8e44ad);
            border-radius: 50%;
            animation: typing-animation 1.4s infinite ease-in-out;
        }

        @keyframes typing-animation {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-4px); }
        }

        .typing-dot:nth-child(2) {
            animation-delay: 0.2s;
        }

        .typing-dot:nth-child(3) {
            animation-delay: 0.4s;
        }
                textarea {
            flex: 1;
            padding: 0.75rem;
            border: 1px solid #565869;
            border-radius: 0.5rem;
            background-color: rgba(64, 65, 79, 0.7);
            color: #FFFFFF;
            resize: none;
            font-size: 1rem;
            min-height: 40px;
            max-height: 200px;
            line-height: 1.5;
            backdrop-filter: blur(10px);
        }

        textarea:focus {
            outline: none;
            border-color: #19c37d;
            box-shadow: 0 0 0 2px rgba(25, 195, 125, 0.2);
        }

        button {
            padding: 0.75rem 1.5rem;
            background: linear-gradient(90deg, #19c37d, #1a8870);
            border: none;
            border-radius: 0.5rem;
            color: white;
            cursor: pointer;
            font-size: 1rem;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(25, 195, 125, 0.2);
        }

        button:disabled {
            background: #565869;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }

        @media (max-width: 768px) {
            .responses-grid {
                grid-template-columns: 1fr;
            }

            .model-card {
                width: 160px;
                height: 100px;
                font-size: 0.9rem;
            }

            .message {
                max-width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="chat-container">
        <div class="chat-header">
            <h1>AI Assistant</h1>
            <div class="model-cards-container" id="modelCards">
                <div class="model-card" data-model="DEEPSEEK_R1">
                    <span>DeepSeek-R1</span>
                    <small>英伟达版</small>
                </div>
                <div class="model-card" data-model="DEEPSEEK_V3">
                    <span>DeepSeek-V3</span>
                    <small>昇腾版</small>
                </div>
                <div class="model-card" data-model="QWEN_72B">
                    <span>Qwen2.5-72B</span>
                    <small>Instruct</small>
                </div>
                <div class="model-card" data-model="BAICHUAN2">
                    <span>Baichuan2</span>
                    <small>Turbo</small>
                </div>
                <div class="model-card" data-model="TELECHAT">
                    <span>TeleChat</span>
                    <small>12B</small>
                </div>
            </div>
        </div>
        <div class="chat-messages" id="messageContainer"></div>
        <div class="chat-input-container">
            <textarea id="userInput" placeholder="输入消息..." rows="1"></textarea>
            <button id="sendButton">
                发送
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M22 2L11 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    <path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            </button>
        </div>
    </div>
        <script>
        let ws = new WebSocket(`ws://${window.location.host}/ws/chat`);
        const messageContainer = document.getElementById('messageContainer');
        const userInput = document.getElementById('userInput');
        const sendButton = document.getElementById('sendButton');
        const modelCards = document.getElementById('modelCards');

        let selectedModels = new Set(['DEEPSEEK_R1']);
        let isMultiModelMode = false;

        userInput.addEventListener('input', function() {
            this.style.height = 'auto';
            this.style.height = Math.min(this.scrollHeight, 200) + 'px';
        });

        modelCards.addEventListener('click', function(e) {
            const card = e.target.closest('.model-card');
            if (!card) return;

            const model = card.dataset.model;

            if (e.ctrlKey || e.metaKey) {
                isMultiModelMode = true;
                if (selectedModels.has(model)) {
                    selectedModels.delete(model);
                    card.classList.remove('selected');
                } else {
                    selectedModels.add(model);
                    card.classList.add('selected');
                }
            } else {
                isMultiModelMode = false;
                selectedModels.clear();
                selectedModels.add(model);
                document.querySelectorAll('.model-card').forEach(c => {
                    c.classList.remove('selected');
                });
                card.classList.add('selected');
            }

            if (selectedModels.size === 0) {
                selectedModels.add('DEEPSEEK_R1');
                document.querySelector('[data-model="DEEPSEEK_R1"]').classList.add('selected');
            }

            addSystemMessage(`已选择模型: ${Array.from(selectedModels).join(', ')}`);
        });

        function addSystemMessage(content) {
            const messageDiv = document.createElement('div');
            messageDiv.className = 'system-message';
            messageDiv.textContent = content;
            messageContainer.appendChild(messageDiv);
            messageContainer.scrollTop = messageContainer.scrollHeight;
        }

        function createResponseCard(model, messageId) {
            const card = document.createElement('div');
            card.className = 'response-card loading';

            const header = document.createElement('div');
            header.className = 'message-header';

            const modelName = document.createElement('span');
            modelName.textContent = document.querySelector(`[data-model="${model}"]`).querySelector('span').textContent;
            header.appendChild(modelName);

            const metrics = document.createElement('div');
            metrics.className = 'response-metrics';
            metrics.innerHTML = '<span class="time">0.0s</span>';

            const content = document.createElement('div');
            content.dataset.messageId = messageId;

            card.appendChild(header);
            card.appendChild(content);
            card.appendChild(metrics);

            return card;
        }

        async function sendMessage() {
            const message = userInput.value.trim();
            if (!message) return;

            sendButton.disabled = true;

            const userMessageDiv = document.createElement('div');
            userMessageDiv.className = 'message user-message';
            userMessageDiv.textContent = message;
            messageContainer.appendChild(userMessageDiv);

            userInput.value = '';
            userInput.style.height = 'auto';

            if (isMultiModelMode) {
                const responsesGrid = document.createElement('div');
                responsesGrid.className = 'responses-grid';
                messageContainer.appendChild(responsesGrid);

                selectedModels.forEach(model => {
                    const messageId = Date.now() + '-' + Math.random().toString(36).substr(2, 9);
                    const card = createResponseCard(model, messageId);
                    responsesGrid.appendChild(card);

                    ws.send(JSON.stringify({
                        message: message,
                        model: model,
                        messageId: messageId
                    }));
                });
            } else {
                const model = selectedModels.values().next().value;
                const messageId = Date.now() + '-' + Math.random().toString(36).substr(2, 9);
                const card = createResponseCard(model, messageId);
                messageContainer.appendChild(card);

                ws.send(JSON.stringify({
                    message: message,
                    model: model,
                    messageId: messageId
                }));
            }

            messageContainer.scrollTop = messageContainer.scrollHeight;
        }

        ws.onmessage = function(event) {
            const data = JSON.parse(event.data);

            if (data.type === "thinking") {
                const targetMessage = document.querySelector(`[data-message-id="${data.messageId}"]`);
                if (targetMessage) {
                    const thinkingIndicator = document.createElement('div');
                    thinkingIndicator.className = 'typing-indicator';
                    thinkingIndicator.innerHTML = `
                        <div class="typing-dot"></div>
                        <div class="typing-dot"></div>
                        <div class="typing-dot"></div>
                    `;
                    targetMessage.appendChild(thinkingIndicator);
                }
                return;
            }

            if (data.type === "stream") {
                const targetMessage = document.querySelector(`[data-message-id="${data.messageId}"]`);
                if (targetMessage) {
                    const thinkingIndicator = targetMessage.querySelector('.typing-indicator');
                    if (thinkingIndicator) {
                        thinkingIndicator.remove();
                    }
                    targetMessage.insertAdjacentText('beforeend', data.content);
                    messageContainer.scrollTop = messageContainer.scrollHeight;
                }
                return;
            }

            if (data.type === "done") {
                const card = document.querySelector(`[data-message-id="${data.messageId}"]`).closest('.response-card');
                if (card) {
                    card.classList.remove('loading');
                    const metrics = card.querySelector('.response-metrics');
                    if (data.metrics) {
                        metrics.innerHTML = `<span class="time">${data.metrics.time.toFixed(2)}s</span>`;
                    }
                }

                const pendingResponses = document.querySelectorAll('.response-card.loading');
                if (pendingResponses.length === 0) {
                    sendButton.disabled = false;
                }
                return;
            }
        };

        sendButton.addEventListener('click', sendMessage);
        userInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        ws.onerror = function(error) {
            console.error('WebSocket错误:', error);
            addSystemMessage('连接错误，请刷新页面重试');
            sendButton.disabled = false;
        };

        ws.onclose = function() {
            console.log('WebSocket连接已关闭');
            addSystemMessage('连接已断开，请刷新页面重试');
            sendButton.disabled = false;
        };

        document.querySelector('[data-model="DEEPSEEK_R1"]').classList.add('selected');
    </script>
</body>
</html>
"""